package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class HotelIndexTest2 {

    private  RestHighLevelClient client;
    @BeforeEach
    public void setUp(){
         client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.200.128:9200")
        ));
    }

    @AfterEach
    public void down(){
        try {
            if (client!=null){
                client.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //查询（匹配所有）
    @Test
    public void findTest()throws IOException{
        //得到request对象
        SearchRequest request=new SearchRequest("hotel");
        //设置条件参数
        request.source().query(QueryBuilders.matchAllQuery());
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析响应数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String source = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }

    //查询（匹配符合条件）
    @Test
    public void findTest2()throws IOException{
        //得到request对象
        SearchRequest request=new SearchRequest("hotel");
        //设置条件参数
        request.source().query(QueryBuilders.matchQuery("name","如家"));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }

    }
    //精确查询
    @Test
    public void preciseTest()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置条件参数
        request.source().query(QueryBuilders.termQuery("city","上海"));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }

    }

    //范围查询
    @Test
    public void rangeTest() throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        request.source().query(QueryBuilders.rangeQuery("price").gt(500).lt(600));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }
    //地理查询
    @Test
    public void geoSearchTest()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        request.source().query(QueryBuilders.geoDistanceQuery("location")
                .distance(15, DistanceUnit.KILOMETERS)
                .point(31.21,121.5));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }
    //布偶查询
    @Test
    public  void boolTest()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("brand","如家"));
        query.filter(QueryBuilders.rangeQuery("price").gte(300).lte(500));
        request.source().query(query);
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }

    //聚合
    @Test
    public  void aggTest()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        BoolQueryBuilder query = QueryBuilders.boolQuery();
      //  query.must(QueryBuilders.termQuery("brand","如家"));
        query.filter(QueryBuilders.rangeQuery("price").gte(300).lte(500));
        request.source().query(query).size(0);
        request.source().aggregation(AggregationBuilders.terms("brand_agg")
                .field("brand")).size(10);

        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        Aggregations aggregations = response.getAggregations();
        if (aggregations!=null){
            Terms agg = aggregations.get("brand_agg");
            List<? extends Terms.Bucket> buckets = agg.getBuckets();
            for (Terms.Bucket bucket : buckets) {
                String key = bucket.getKeyAsString();
                System.out.println(key);
            }
        }
    }
    //普通字段排序
    @Test
    public void sortTest01()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().sort("score", SortOrder.DESC);
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }
    //地理坐标排序
    @Test
    public void geo_Sort()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        request.source().query(QueryBuilders.matchAllQuery());

        request.source().sort(SortBuilders.geoDistanceSort("location",new GeoPoint("31.034661,121.612282"))
                .order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }

    }
    //分页查询
    @Test
    public void pageFindTest()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        int page=1;
        int size=3;
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().from(page).size(size);
        request.source().sort("score",SortOrder.DESC);
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }
    //高亮
    @Test
    public void highLight()throws IOException{
        //得到request对象
        SearchRequest request = new SearchRequest("hotel");
        //设置参数
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        request.source().highlighter(new HighlightBuilder().field("name")
               .requireFieldMatch(false));
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析数据
        long total = response.getHits().getTotalHits().value;
        System.out.println("共搜索到"+total+"条数据");
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            //获取highlight
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)){
                HighlightField field = highlightFields.get("name");
                if (field!=null ){
                    Text[] fragments = field.fragments();
                    if (fragments!=null&&fragments.length>0){
                        String join = StringUtils.join(fragments);
                        hotelDoc.setName(join);
                    }
                }
            }
            System.out.println(hotelDoc);
        }
    }
}
